package tech.autumn.exception.resolver;

import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.stream.Collectors;

/**
 * 参数验证异常处理器
 * 如果参数验证不通过，则返回 400 状态码，并在返回JSON中携带具体信息。
 * @author koko
 * @date 2025年01月21日 14:34
 */
public class HandlerValidationExceptionResolver extends AbstractHandlerExceptionJsonResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        if (ex instanceof IllegalArgumentException || ex instanceof HttpMessageNotReadableException) {
            return badRequest(ex.getMessage());
        } else if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException me = (MethodArgumentNotValidException) ex;
            return badRequest(determineMessage(me.getBindingResult()));
        } else if (ex instanceof BindException) {
            BindException be = (BindException) ex;
            return badRequest(determineMessage(be.getBindingResult()));
        }
        return null;
    }


    private ModelAndView badRequest(String message) {
        return fail(HttpStatus.BAD_REQUEST, message);
    }


    protected String determineMessage(BindingResult result) {
        return result.getFieldErrors().stream().map(fe -> {
            if (isEmpty(fe.getRejectedValue())) {
                return "字段[" + fe.getField() + "]" + fe.getDefaultMessage();
            } else {
                return "字段[" + fe.getField() + "]值[" + fe.getRejectedValue() + "]不合法，" + fe.getDefaultMessage();
            }
        }).collect(Collectors.joining("；")) + "。";
    }

    private boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj instanceof String) {
            return ((String) obj).isEmpty();
        }
        return false;
    }



}
